package probe.logic;

import java.util.ArrayList;

public class Add {

	private Task _task;
	private String[] _taskDetails;
	private String _message;
		
	private static final int MAX_PARAMETERS = 6;
	private static final int MIN_REQUIRED_PARAMETERS = 2;
	
	private static final String SPACE = " ";
	private static final String EARLIEST_TIME = "0000";
	private static final String LATEST_TIME = "2359";
	
	private static final String ERROR_MESSAGE_1 = "No Date or Time Entered";
	private static final String ERROR_MESSAGE_2 = "Invalid Date or Time Entered";
	private static final String ERROR_MESSAGE_3 = "Date or Time Does not Exist";
		
	private static final int TASKNAME_INDEX= 0;
	private static final int FIRST_TIME_DATE_INDEX = 1;
	private static final int SECOND_TIME_DATE_INDEX = 2;
	
	private static final int START_DATE_INDEX = 1;
	private static final int START_TIME_INDEX = 2;
	private static final int END_DATE_INDEX = 3;
	private static final int END_TIME_INDEX = 4;
	private static final int TASKTYPE_INDEX = 5;
	
	private static final int FIRST_INDEX = 0;
	private static final int SECOND_INDEX = 1;
	private static final int THIRD_INDEX = 2;
	
	
	
	public Add() {
		
		_task = new Task();
		_taskDetails = new String [MAX_PARAMETERS];
		_message = null;
		
	}
	
	private void initialise() {
		_task = new Task();
		_taskDetails = new String [MAX_PARAMETERS];
		_message = null;
	}
	
	private void breakdownDetails(String[] commandDetails) {
		
		String[] dateTimeDetails;
		
		if(!checkForTimeAndDate(commandDetails)) {
			_taskDetails[TASKNAME_INDEX] = commandDetails[TASKNAME_INDEX];
			_taskDetails[TASKTYPE_INDEX] = "FLOATING TASK";
		} else {
			
			if(commandDetails[FIRST_TIME_DATE_INDEX].startsWith("-from")) {
				_taskDetails[TASKNAME_INDEX] = commandDetails[TASKNAME_INDEX];
				dateTimeDetails = retrieveDetails(commandDetails[FIRST_TIME_DATE_INDEX]);
				assignDetails(dateTimeDetails);
				dateTimeDetails = retrieveDetails(commandDetails[SECOND_TIME_DATE_INDEX]);
				assignDetails(dateTimeDetails);
		
			} else {
				_taskDetails[TASKNAME_INDEX] = commandDetails[TASKNAME_INDEX];
				dateTimeDetails = retrieveDetails(commandDetails[FIRST_TIME_DATE_INDEX]);
				assignDetails(dateTimeDetails);
			}
		}
	}		
	
	private String [] retrieveDetails(String details) {
		
		String [] dateTimeDetails = details.split(SPACE);
		return dateTimeDetails;
	}
	
	private void assignDetails(String[] details) {
		
		if(details[FIRST_INDEX].equals("-from")) {
			_taskDetails[TASKTYPE_INDEX] = "STET TASK";
			assignStartDetails(details);
		}
		
		if(details[FIRST_INDEX].equals("-to")) {
			_taskDetails[TASKTYPE_INDEX] = "STET TASK";
			assignEndDetails(details);
		}
		
		if(details[FIRST_INDEX].equals("-at") || details[FIRST_INDEX].equals("-by")) {
			_taskDetails[TASKTYPE_INDEX] = "DEADLINE TASK";
			assignEndDetails(details);
		}
	}

	private void assignEndDetails(String[] details) {
		
		if(details.length == MIN_REQUIRED_PARAMETERS) {
			_taskDetails[END_DATE_INDEX] = details[SECOND_INDEX];
			_taskDetails[END_TIME_INDEX] = LATEST_TIME;
		} else if(details.length < MIN_REQUIRED_PARAMETERS) {
			_message = ERROR_MESSAGE_1;
		} else {
			_taskDetails[END_DATE_INDEX] = details[SECOND_INDEX];
			_taskDetails[END_TIME_INDEX] = details[THIRD_INDEX];
		}
	}

	private void assignStartDetails(String[] details) {
		
		if(details.length == MIN_REQUIRED_PARAMETERS) {
			_taskDetails[START_DATE_INDEX] = details[SECOND_INDEX];
			_taskDetails[START_TIME_INDEX] = EARLIEST_TIME;
		} else if(details.length < MIN_REQUIRED_PARAMETERS) {
			_message = ERROR_MESSAGE_1;
		} else {
			_taskDetails[START_DATE_INDEX] = details[SECOND_INDEX];
			_taskDetails[START_TIME_INDEX] = details[THIRD_INDEX];
		}
	}
	
	private boolean checkForTimeAndDate (String[] commandDetails) {
		
		if(commandDetails.length < MIN_REQUIRED_PARAMETERS )
			return false;
		else
			return true;
	}
	
	private boolean checkforErrorMessage() {
		if(_message == null) {
			return false;
		} else return true;
	}
	
	private boolean createTask() {
		
		if(_taskDetails[TASKTYPE_INDEX].equals("FLOATING TASK")){
			return createFloatingTask();
		}
		if(_taskDetails[TASKTYPE_INDEX].equals("DEADLINE TASK")) {
			return createDeadLineTask();
		}
		if(_taskDetails[TASKTYPE_INDEX].equals("STET TASK")) {
			return createSTETTask();
		}
		
		return false;
	}

	private boolean createFloatingTask() {
		_task.taskName = _taskDetails[TASKNAME_INDEX];
		_task.taskType = Task.TaskType.FLOATING_TASK;
		return true;
	}

	private boolean createSTETTask() {
		
		try {
			Date startingDate = new Date(_taskDetails[START_DATE_INDEX]);
			Time startingTime = new Time(_taskDetails[START_TIME_INDEX]);
			Date endingDate = new Date(_taskDetails[END_DATE_INDEX]);
			Time endingTime = new Time(_taskDetails[END_TIME_INDEX]);
		
			if(verifyDateTime(startingDate, startingTime) && verifyDateTime(endingDate, endingTime) ) {
				_task.taskName = _taskDetails[TASKNAME_INDEX];
				_task.endingDate = endingDate;
				_task.endingTime = endingTime;
				_task.startingDate = startingDate;
				_task.startingTime = startingTime;
				_task.taskType = Task.TaskType.STET_TASK;
				return true;
			} else {
				_message = ERROR_MESSAGE_3;
				return false;
			}
		} catch (NumberFormatException e) {
			_message = ERROR_MESSAGE_2;
			return false;
		}
	}

	private boolean createDeadLineTask() {
		
		try {
			Date deadLineDate = new Date(_taskDetails[END_DATE_INDEX]);
			Time deadLineTime = new Time(_taskDetails[END_TIME_INDEX]);
			if(verifyDateTime(deadLineDate,deadLineTime)) {
				_task.taskName = _taskDetails[TASKNAME_INDEX];
				_task.deadline = deadLineDate;
				_task.time = deadLineTime;
				_task.taskType = Task.TaskType.DEADLINE_TASK;
				return true;
			} else {
				_message = ERROR_MESSAGE_3;
				return false;
			}
		} catch (NumberFormatException e) {
			_message = ERROR_MESSAGE_2;
			return false;
		}
	}
		
	private boolean verifyDateTime(Date date, Time time) {
		
		return date.isValidDate() & time.isValidTime();
	}

	private ArrayList<Task> add(ArrayList<Task> list) {
		
		_task.taskStatus = Task.TaskStatus.UNFINISHED;
		list.add(_task);
		return list;
	}
	
	public String getMessage() {
		return _message;
	}

	public ArrayList<Task> process (ArrayList<Task> list, String[] commandDetails) {
		
		initialise();
		breakdownDetails(commandDetails);
		if(checkforErrorMessage()) {
			return list;
		} else {
			if(createTask()) {
				return add(list);
			} else {
				return list;
			}
		}
	}
}
